﻿#include <dlfcn.h>
#include <iostream>
#include <vector>
#include <chrono>
#include <thread>
#include "plugin.h"

struct PluginDeleter
{
    PluginDeleter(void (*destroyPlugin)(Plugin *)) : destroyPlugin(destroyPlugin) {}

    void operator()(Plugin *plugin) const
    {
        destroyPlugin(plugin);
    }

    void (*destroyPlugin)(Plugin *);
};

bool isLibraryUpdated(const std::string &libraryPath, std::string &currentVersion)
{
    void *handle = dlopen(libraryPath.c_str(), RTLD_LAZY | RTLD_LOCAL);
    if (handle)
    {
        // 获取动态库中的版本号
        const char *(*getVersion)() = reinterpret_cast<const char *(*)()>(dlsym(handle, "getVersion"));
        if (getVersion)
        {
            const char *libraryVersion = getVersion();
            if (libraryVersion != currentVersion)
            {
                currentVersion = libraryVersion;
                dlclose(handle); // 关闭动态库
                return true;     // 版本号不一致，说明动态库已更新
            }
        }
        dlclose(handle); // 关闭动态库
    }
    return false; // 动态库未更新或加载失败
}

int main()
{
    std::string libraryPath = "./libplugins.so";
    std::string currentVersion; // 当前版本号

    while (true)
    {
        if (isLibraryUpdated(libraryPath, currentVersion))
        {
            void *handle = dlopen(libraryPath.c_str(), RTLD_LAZY);
            if (!handle)
            {
                std::cerr << "Failed to load library: " << dlerror() << std::endl;
                return -1;
            }
            int a;
            std::cout << "handle:" << &a << std::endl;

            {
                using CreatePluginFunc = Plugin *(*)();
                using DestroyPluginFunc = void (*)(Plugin *);

                CreatePluginFunc createFooPlugin = reinterpret_cast<CreatePluginFunc>(dlsym(handle, "createFooPlugin"));
                if (!createFooPlugin)
                {
                    std::cerr << "Failed to get function address: " << dlerror() << std::endl;
                    return -1;
                }

                CreatePluginFunc createBarPlugin = reinterpret_cast<CreatePluginFunc>(dlsym(handle, "createBarPlugin"));
                if (!createBarPlugin)
                {
                    std::cerr << "Failed to get function address: " << dlerror() << std::endl;
                    return -1;
                }

                DestroyPluginFunc destroyPlugin = reinterpret_cast<DestroyPluginFunc>(dlsym(handle, "destroyPlugin"));
                if (!destroyPlugin)
                {
                    std::cerr << "Failed to get function address: " << dlerror() << std::endl;
                    return -1;
                }

                std::vector<std::unique_ptr<Plugin, PluginDeleter>> plugins;
                plugins.emplace_back(createFooPlugin(), PluginDeleter(destroyPlugin));
                plugins.emplace_back(createBarPlugin(), PluginDeleter(destroyPlugin));

                for (auto &plugin : plugins)
                {
                    plugin->doSomething();
                }
            }
            dlclose(handle);
        }
        else
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }
}